﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleData.Infrastructure.Serialization
{

	
	/// <summary>
	/// Realiza a serialização de deserialização de <typeparamref name="TValue"/>.
	/// </summary>
	/// <typeparam name="TValue"></typeparam>
	public sealed class DataObjectSerializable<TValue> : IDataObjectSerializable<TValue>
	{
		private TValue value;
		private byte[] serializedValue;

		#region [ .ctor ]

		public DataObjectSerializable( IDataObjectStreamer streamer )
		{
			streamer.Throws().IfNull();
			this.Streamer = streamer;
		}

		public DataObjectSerializable( TValue value, IDataObjectStreamer streamer )
			: this( streamer )
		{
			this.Value = value;
		}

		public DataObjectSerializable( byte[] value, IDataObjectStreamer streamer )
			: this( streamer )
		{
			this.SerializedValue = value;
		}

		#endregion

		/// <summary>
		/// Obtém ou define a estratégia para realizar a serialização dos objetos
		/// </summary>
		public IDataObjectStreamer Streamer
		{
			get;
			private set;
		}

		/// <summary>
		/// 
		/// </summary>
		public SerializableState State
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém o valor deserializado
		/// </summary>
		public TValue Value
		{
			get
			{
				if ( !this.IsDeserialized )
				{
					this.value = this.Streamer.DeserializeAs<TValue>( this.serializedValue );
					this.State |= SerializableState.Deserialized;
				}
				return this.value;
			}
			set
			{
				this.value = value;
				this.ValueChanged();
				//this.State = SerializableState.Deserialized;
			}
		}

		/// <summary>
		/// Obtém o valor serializado
		/// </summary>
		public byte[] SerializedValue
		{
			get
			{
				if ( !this.IsSerialized )
				{
					this.serializedValue = this.Streamer.Serialize( this.Value );
					this.State |= SerializableState.Serialized;
				}
				return this.serializedValue;
			}
			set
			{
				this.serializedValue = value;
				this.State = SerializableState.Serialized;
			}
		}

		/// <summary>
		/// Indica que o valor foi alterado
		/// </summary>
		public void ValueChanged()
		{
			this.State = SerializableState.Deserialized;
		}

		private bool IsSerialized
		{
			get { return Convert.ToBoolean( this.State & SerializableState.Serialized ); }
		}

		private bool IsDeserialized
		{
			get { return Convert.ToBoolean( this.State & SerializableState.Deserialized ); }
		}
	}
}
